package com.service;

import com.entity.User;
import com.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class UserService {
    /*将方法的运行结果进行缓存，后面再使用相同数据，直接从缓存中获取，不能调用方法
     * CacheManager管理多个Cache组件，对缓存的真正CRUD操作在cache组件中，每一个缓存组建有自己唯一的一个名字
     * 几个属性：
     * cacheNames/value:指定缓存的名字；
     * key:缓存数据使用的key；可以用它来指定。默认使用方法参数的值 1-方法的返回值
     *           编写Spel
     * keyGenerator:key的生成器；可以自己指定key 的生成器的组建ID
     * cacheManager：指定缓存管理器；或者cacheResolver指定获取解析器
     * condition：指定符合条件的情况才缓存；，condition="#id>0"：第一个参数的值》1的时候才进行缓存
     * unless:否定缓存；当unless指定的条件为true，方发的返回值就不会被缓存；可以获取到结果进行判断
     * unless=“#result==Null”
     * unless="#a0==2":如果第一个参数的值为2，结果不缓存
     * sync：是否使用异步模式*/
    /*
     * 打开缓存，并设置缓存名称为user
     */

    @Autowired
    UserMapper usermapper;

    //todo 2.@Cacheable：用于方法上，表示方法的结果应该被缓存。

    @Cacheable(cacheNames = {"user"})//设置缓存名称为user
    public User getUserById(int id) {
        System.out.println("查询" + id + "号员工");
        return usermapper.selectById(id);
    }

    //todo 3.@CachePut：用于方法上，表示方法的结果应该更新缓存。
    /*@CachePut:既调用方法，又更新缓存数据;同步更新缓存；
    * 修改了数据库的某个数据，同时更新缓存*
    运行时机：
    1、先调用目标方法
    2、将目标方法的结果缓存起来
    * 测试步骤：
    *   1、查询1号员工；查到的结果会放在缓存中
    *   2、以后查询还是之前的结果
    *   3、更新1号员工；【】
    *           将方法的返回值也放进缓存了；
    *           key：传入的user对象  值：返回的user对象
    * 4、查询1号员工?
    *   应该是更新后的员工：
    *       key="#result.id"使用返回后的id
    *       key="#user.id"使用传入的参数的员工的id
    * @cacheable的key是不能用#result
    * 为什么是没有更新前的？【1号员工没有在缓存中更新】
     */
    @CachePut(value = "user", key = "#result.id")//使用传入的参数id,也就是修改的数据中对应的id
    public User updateUser(User user) {
        System.out.println("updateUser:" + user);
        usermapper.updateById(user);
        return user;
    }


    /* todo 4. @CacheEvict：用于方法上，表示从缓存中删除条目。

     *
     *@CacheEvict缓存清空
     * key：指定要清除的数据
     * allEntries=true:指定清除这个缓存中所有的数据
     * beforeInvocation=false缓存的清楚是否在方法之前执行，默认代表缓存清除是在方法执行之后执行
     * beforeInvocation=true  代表缓存清除是在方法执行之前执行*/
    @CacheEvict(value = "user", key = "#id")
    @Transactional
    public void userDelete(Integer id) {
        System.out.println("deleteuser:" + id);
        usermapper.deleteById(id);
    }


//    //定义复杂的缓存规则
//    @Caching(
//            cacheable = {@Cacheable(value="emp",key="#lastName")},
//    put = {
//            @CachePut(value = "emp",key="#result.id"),
//            @CachePut(value = "emp",key = "#result.email")
//    }
//    )
//    public User getUserByLastName(String lastName)
//    {
//        return usermapper.getUserByLastName(lastName);
//    }
}
